rm(list = ls(all = TRUE))
setwd("C:\\Users\\lenovo\\Desktop\\R\\神经网络_R语言实现")

#循环神经网络：recurrent neural network，RNN
#卷积神经网络：convolutional neural network，CNN

#6.1 循环神经网络
#神经元之间形成一种循环，
#与前馈网络不同，RNN可以使用内部存储器进行处理
#RNN是一种人类神经网络，
#其特征在于隐含层之间的连接按时间传播以便学习序列

#循环神经网络不仅将当前输入到网络的数据作为它们的输入，
#而且还将它们长期以来的经历作为输入

#循环神经网络与前馈网络的区别在于反馈回路与其过去的决策相关联
#因此将过去的输出暂时作为输入接收

#为神经网络增加记忆的目的是：序列本身有信息，
#而循环神经网络可以使用它来执行前馈网络不能完成的任务

#总之，RNN是一类神经元之间存在连接并形成有向循环的神经网络
#一个实例的输出作为同一个神经元的下一个实例的输入

#在RNN下，数据向后流动的方式有较多变体：
#完全递归（fully recurrent）
#递归（recursive）
#Hopfield
#Elman和Jordan网络
#神经历史压缩机（neural history compressor）
#LSTM
#门控循环单元（Gated Recurrent Unit，GRU）
#双向网络（bidirectional）
#循环MLP（recurrent MLP）

#RNN旨在将模式识别为一系列数据，并有助于预测
#install.packages("rnn")
#install.packages("mxnetr")
#install.packages("tensorflow")

#RNN组要被用于序列建模，输入和输出被视为向量（数字矩阵）

#6.2 R中的添加包rnm

#install.packages("rnn")
library(rnn)
#install.packages("digest")
run.rnn_demo()

#trainer(Y,X,
#        learningrate,
#        learningrate_decay = 1,
#        momentum = 0,
#        hidden_dim = c(10),
#        network_type = "rnn",
#        numepochs = 1,
#        sigmoid = c("logistic","Gompertz","tanh"),
#        use_bias = F,
#        batch_size = 1,
#        seq_to_seq_unsync = F,
#        update_rule = "sgd",
#        epoch_function = c(epoch_print,epoch_annealing),
#        loss_function = loss_L1, ...)

#predict(model,
#        X,
#        hidden = FALSE,
#        real_output = T,
#        arguments to pass to sigmoid function)


#X1和X2的随机数在0~127之间，Y被初始化为X1+X2.
#将X1、X2和Y转换为二进制变量后，使用trainer基于X训练Y

library(rnn)

#Create a set of random numbers in X1 and X2
X1 = sample(0:127, 7000, replace = TRUE)
X2 = sample(0:127, 7000, replace = TRUE)

#Create training response numbers
Y = X1 + X2

#Convert to binary
X1 = int2bin(X1)
X2 = int2bin(X2)
Y = int2bin(Y)

#Create 3d array: dim1: samples; dim2: time; dim3: variables
X = array(c(X1,X2), dim = c(dim(X1),2))

#Train the model
model <- trainr(Y = Y[,dim(Y)[2]:1],
                 X = X[,dim(Y)[2]:1,],
                 learningrate = 0.1,
                 hidden_dim = 10,
                 batch_size = 100,
                 numepochs = 100)

plot(colMeans(model$error), type = 'l', xlab = 'epoch',
     ylab = 'errors')

#Create test inputs
A1 = int2bin(sample(0:127, 7000, replace = TRUE))
A2 = int2bin(sample(0:127, 7000, replace = TRUE))

#Create 3d array: dim1: samples; dim2: time; dim3: variables
A = array(c(A1,A2), dim = c(dim(A1),2))

#Now, let us run prediction for new A
B = predictr(model,
            A[,dim(A)[2]:1,])
B = B[,dim(B)[2]:1]

#Convert back to integers
A1 = bin2int(A1)
A2 = bin2int(A2)
B = bin2int(B)

#Plot the differences as histogram
hist(B-(A1+A2))

#6.3 LSTM模型
#RNN具有将持续的先前信息用于当前神经网络处理的记忆
#先前的记忆是短期地，并且我们没有可用于神经节点的所有先前信息的列表
#当将长期记忆引入RNN时，RNN便能记住大量先前信息并将其用于当前的处理中


#LSTM网络使用基于时间的反向传播进行训练并减少梯度消失问题

#输入门、输出门、遗忘门

#直接序列预测、序列分类、序列生成、序列预测生成

#GRU有2个门、LSTM有3个门
#GRU不具有任何与宝库的隐含状态不同的内部存储块
#在计算GRU的输出时，只应用一个非线性过程


#6.4 卷积神经网络

#专门用于图像识别与分类
#CNN具有多层神经网络，从图像中提取信息并确定它们所属的类别

#任何图像只是一组向量格式的RGB数字，如果可以让神经网络理解模式。
#那么它可以构建CNN并检测图像

#常规的神经网络在图像分析中不能很好地扩展
#在CNN中，CNN的层具有三维（高度、宽度和深度）排列的神经元

#CNN是一系列神经网络层，其中每层通过可微分函数将一个三维的
#激活函数转换为另一个

#构建CNN神经网络层有三类
#卷积层（convolutional layer）
#池化层（pooling layer）
#全连接层（fully connected layer）

#第1步：过滤
#卷积层执行繁重的数学运算。
#计算机视觉中处理图像的典型方法是使用过滤器对其进行卷积，
#以提取其中的显著特征
#输入图像应用过滤器逻辑来创建激活映射（activation map）
#或特征映射（feature map）

#将特征和图像块排成一行
#将每个图像像素乘以相应的特征像素
#将结果加总
#按特征像素的总数划分加总结果

#第2步：池化
#缩小图像堆栈
#对于在卷积步骤中获得的每个特征，建立一个矩阵，
#然后在每个选定矩阵中找到最大值以收缩整个输入

#选择一个窗口大小（通常为2或3）
#选择像素的一个步移动范围（通常为2）
#将窗口滑过已过滤的图像
#对于每个窗口。选取最大值

#如果滑动窗口没有先前窗口所需的单元格数量，则采取任何可用的值


#第3步：使用RelU进行标准化
#在这一步中，选取池化输出和每个像素，应用ReLU进行标准化，
#如果任何一个值为负数，则将其设为零


#第4步：全连接层中的投票和分类
#最后一层是全连接层。对该组值进行投票以确定输出的类别
#全连接层只是先前所有输出的合并矩阵


#合并第1-3步中的层，形成了卷积网络，可以通过反向传播
#来减少误差项以给出最好的预测

#这些层可以重复多次，每个层的输出形成下一个层的输入


#6.5 常见的CNN架构——LeNet
#LeNet-5是20世纪90年代Le Cun为识别手写和机器打印字符设计的卷积网络
#卷积-池化-卷积-池化-全连接-全连接-输出预测


#6.6 使用RNN进行适度预测

#这个例子的目的是预测某一地点每天的湿度以获得一个函数

rm(list = ls(all = TRUE))
setwd("C:\\Users\\lenovo\\Desktop\\R\\神经网络_R语言实现")

#install.packages("rattle.data")
library(rattle.data)
library(rnn)

data(weatherAUS)
View(weatherAUS)

#extract only 1 and 14 clumn and first 3040 rows(Albury location)
data = weatherAUS[1:3040,c(1,14)]
summary(data)

data_cleaned <- na.omit(data)
data_used = data_cleaned[1:3000]

x = data_cleaned[,1]
y = data_cleaned[,2]

head(x)
head(y)

#化为矩阵
X = matrix(x, nrow = 30)
Y = matrix(y, nrow = 30)

# Standardize in the interval 0 - 1
Yscaled = (Y - min(Y)) / (max(Y) - min(Y))
Y = t(Yscaled)
train = 1:70
test = 71:100

model <- trainr(Y = Y[train,],
                X = Y[train,],
                learningrate = 0.05,
                hidden_dim = 16,
                numepochs = 1000)
#绘制算法产生的误差随epoch的变化来查看算法的演变
plot(colMeans(model$error), type = "l", xlab = 'epoch', ylab = 'errors')

Yp <- predictr(model, Y[test,])

plot(as.vector(t(Y[test,])), col = 'red', type = 'l',
     main = "Actual vs Predicted Humidity: testing set",
     ylab = "Y,Yp")
lines(as.vector(t(Yp)), type = 'l', col = 'black')
legend("bottomright", c("Predicted","Actual"),
       col = c("red", "black"),
       lty = c(1,1), lwd = c(1,1))
#由图可得，数据得到了很好的拟合，这说明该模型可以很好地预测湿度。


